import time
import json
import atexit
import signal
import threading
import copy
import re
import logging


logger = logging.getLogger(__name__)

class PlannerLogger:
    _instance = None
    _lock = threading.Lock()

    def __new__(cls, *args, **kwargs):
        if not cls._instance:
            with cls._lock:
                if not cls._instance:
                    cls._instance = super(PlannerLogger, cls).__new__(cls)
                    cls._instance._initialized = False
        return cls._instance

    def __init__(self):
        if not self._initialized:
            self.current_data = {
                "timestamp": 0.0,
                "iterations": 0,
                "parameters": dict(),
                "state": dict(),
                "track": dict()
            }
            self.log = []
            self.lock = threading.Lock()
            self.last_saved_index = 0
            self._initialized = True
            self.log_file_path = None
            self.file = None

            atexit.register(self._save_on_exit)
            signal.signal(signal.SIGINT, self._signal_handler)
            signal.signal(signal.SIGTERM, self._signal_handler)

            self.auto_save_interval = 3  # 自动保存间隔，单位为秒
            self.auto_save_thread = threading.Thread(target=self._auto_save, daemon=True)
            self.auto_save_thread.start()

    def load_file(self, file: str = None):
        self.log_file_path = file
        self.file = open(file, 'a+')
        if self.file.tell() == 0:
            self.file.write('[\n')

    def _save_on_exit(self):
        """程序退出时自动保存日志"""
        self.save_log(clear_after_save=True)
        self._cleanup(True)

    def _signal_handler(self, signum, frame):
        """捕获信号并保存日志"""
        logger.info(f"Signal {signum} received, saving log...")
        self.save_log(clear_after_save=True)
        self._cleanup(True)
        exit(0)

    def _auto_save(self):
        """后台线程定期自动保存日志"""
        while True:
            time.sleep(self.auto_save_interval)
            self.save_log(clear_after_save=True)

    def save_log(self, clear_after_save=False):
        with self.lock:
            # 只保存从上次保存后的新数据
            new_entries = self.log[self.last_saved_index:]
            if not new_entries:
                return  # 如果没有新数据则不保存
            try:
                # 追加新数据到文件
                for i, entry in enumerate(new_entries):
                    if self.file.tell() > 2:  # 不是第一个条目，添加逗号
                        self.file.write(',\n')
                    json.dump(entry, self.file)
                self.file.flush()
                # 更新保存的索引
                self.last_saved_index = len(self.log)
                if clear_after_save:
                    self.log.clear()
                    self.last_saved_index = 0
            except Exception as e:
                print(f"Error saving log: {e}")

    def _cleanup(self, final=False):
        """清理函数，在程序退出时关闭文件"""
        with self.lock:
            if self.file:
                if final:
                    self.file.seek(0, 2)  # 确保文件指针在末尾
                    self.file.write('\n]')
                self.file.close()
                self.file = None

    def update_data(self, name, state: dict = None, track: dict = None):
        if state is not None:
            self.current_data["state"][name] = state
        if track is not None:
            self.current_data["track"][name] = track

    def update_args(self, name, args):
        param = vars(args)
        self.current_data["parameters"][name] = param


    def record_(self, index):
        with self.lock:
            timestamps = time.time()
            self.current_data["timestamp"] = timestamps
            self.current_data["iterations"] = index
            self.log.append(copy.deepcopy(self.current_data))
            self.current_data["timestamp"] = 0.0
            self.current_data["track"] = dict()
            self.current_data["state"] = dict()